nv.defineSingleton("nv.util.Dom", function ($this) {
    $this.loadCssFile = function (href) {
        var stylesheet = document.createElement("link");
        stylesheet.rel = "stylesheet";
        stylesheet.type = "text/css";
        stylesheet.href = href;
        stylesheet.media = "all";
        $this.safeAddNodeToHead(stylesheet);
    };
    $this.addJSToHead = function (jsUrl, completionCallback) {
        var scriptNode = document.createElement("SCRIPT");
        if (typeof completionCallback == 'function') {
            attachOnLoadCallbackToScriptNode(scriptNode, completionCallback);
        }
        scriptNode.type = 'text/javascript';
        scriptNode.src = jsUrl;
        $this.safeAddNodeToHead(scriptNode);
        return scriptNode;
    };
    var attachOnLoadCallbackToScriptNode = function (scriptNode, loadCallback, errorCallback) {
        var wrapCallback = function (callback) {
            if (typeof callback != 'function') return function () {};
            return function () {
                if (!scriptNode.onloadDone) {
                    scriptNode.onloadDone = true;
                    callback();
                }
            };
        };
        if (scriptNode.addEventListener) {
            scriptNode.addEventListener("load", wrapCallback(loadCallback), false);
            if (typeof errorCallback == 'function') {
                scriptNode.addEventListener("error", wrapCallback(errorCallback), false);
            }
        } else if (scriptNode.readyState) {
            scriptNode.onreadystatechange = function () {
                if (scriptNode.readyState == "loaded" || scriptNode.readyState == "complete") {
                    wrapCallback(loadCallback)();
                }
            };
        }
    };
    $this.safeAddNodeToHead = function (node, frameDocument) {
        if (typeof frameDocument == "undefined") {
            frameDocument = document;
        }
        var timerEvent = function () {
            if (frameDocument.body) {
                frameDocument.getElementsByTagName("head")[0].appendChild(node);
            } else {
                setTimeout(timerEvent, 200);
            }
        };
        timerEvent();
    };
    $this.addCssStylesToDom = function (styleString, frameDocument) {
        if (typeof frameDocument == "undefined") {
            frameDocument = document;
        }
        if (frameDocument.createStyleSheet) {
            var stylesheet = frameDocument.createStyleSheet();
            stylesheet.cssText = styleString;
        } else {
            var stylesheet = frameDocument.createElement("style");
            var prop = "innerHTML";
            if (navigator.userAgent.indexOf("Safari") != -1) {
                prop = "innerText";
            }
            stylesheet[prop] = styleString;
            $this.safeAddNodeToHead(stylesheet, frameDocument);
        }
    };
    $this.ieContentLoaded = function (w, fn) {
        var d = w.document,
            done = false,
            init = function () {
                if (!done) {
                    done = true;
                    fn();
                }
            };
        (function () {
            try {
                d.documentElement.doScroll('left');
            } catch (e) {
                setTimeout(arguments.callee, 50);
                return;
            }
            init();
        })();
        d.onreadystatechange = function () {
            if (d.readyState == 'complete') {
                d.onreadystatechange = null;
                init();
            }
        };
    };
});